import _ from 'lodash'
import { article, desc, section } from './lablog.js'
import path from 'path'

const IO = function(f) {
    this.__value = f
}
IO.of = function(x) {
    return new IO(function() {
        return x
    })
}
IO.prototype.map = function(f) {
    return new IO(_.flowRight(f, this.__value))
}

const split = _.curryRight(function(str, delimeter) {
    return _.split(str, delimeter)
})

article("IO 的 __value 是一个函数。它将非纯执行动作捕获到包裹函数里，目的是延迟执行这个非纯动作。就这点而言，我们认为 IO 包裹的是被包裹的执行动作的返回值，而不是包裹函数本身。")
const io_window = new IO(function() {return global;})
console.log(io_window.map(function(win) {return win.process}))
console.log(io_window.map(_.property('env')).map(_.property('BASH')).map(split('/')))

const map = _.curry(function(f, functor) {
    return functor.map(f)
})

const m_global = new IO(function() {return global})
const gProcess = m_global.map(function(global) {return global.process})
const nodeEnv = gProcess.map(_.property('env')).map(_.property('NODEJS_HOME'))
const splitPath = split(path.sep)
const unsafePerform = () => {
    return map(splitPath, nodeEnv)
}

// console.log(splitPath('/hello/world'))
console.log(unsafePerform().__value())

desc("通俗来讲，一个函数在调用的时候，如果被 map 包裹了，那么它就会从一个非 functor 函数转变为一个 functor 函数。我们将这个过程称为 lift。一般情况下，普通函数更适合操作普通的数据类型而不是容器类型。在必要的时候再通过 lift 变为合适的容器去操作容器类型。这样做的好处是能够得到更简单、重用性更高的函数。它们能够随需求而变，兼容任意 functor")
